package com.lingyun.framework.aspect;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.lingyun.common.annotation.DataJurisdiction;
import com.lingyun.common.corebase.BaseEntity;
import com.lingyun.common.exception.ServiceException;
import com.lingyun.common.pojo.LyRole;
import com.lingyun.common.pojo.LyUser;
import com.lingyun.common.utils.security.SecurityUtils;
import com.lingyun.common.vo.LoginUser;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 没事别学JAVA
 * 2021/12/28 2:59
 */

@Aspect
@Component
public class DataJurisdictionAspect {

    /**
     * 全部数据权限
     */
    public static final String DATA_SCOPE_ALL = "1";

    /**
     * 自定数据权限
     */
    public static final String DATA_SCOPE_CUSTOM = "2";

    /**
     * 角色数据权限
     */
    public static final String DATA_SCOPE_ROLE = "3";


    /**
     * 数据权限过滤关键字
     */
    public static final String DATA_SCOPE = "dataScope";



//    @Before("@annotation(dataJurisdiction)")    ////@annotation声明以注解的方式来定义切点
//    public void beforeMethod(JoinPoint joinPoint,DataJurisdiction dataJurisdiction){
//    }

    /**
     * 业务逻辑开始之前执行
     * @param joinPoint
     * @param
     */
    @Before("@annotation(com.lingyun.common.annotation.DataJurisdiction)")    ////@annotation声明以注解的方式来定义切点  上面注释的是另一种写法 如果你需要往自定义注解中传值的话
    public void beforeMethod(JoinPoint joinPoint){
        System.out.println("业务逻辑开始执行之前执行.......");
        clearDataScope(joinPoint);
        handleDataScope(joinPoint);
    }
    /**
     *
     * 数据处理
     *
     */
    public void handleDataScope(final JoinPoint joinPoint){
        LoginUser loginUser=null;
        try {
            loginUser=SecurityUtils.getLoginUser();
        } catch (ServiceException e) {
            e.printStackTrace();
        }
        if(ObjectUtil.isNotNull(loginUser)){
            LyUser lyUser=loginUser.getLyUser();
            if(!loginUser.getRoles().contains("admin")){
                dataScopeFilter(joinPoint,lyUser);
            }
        }
    }
    /**
     * 数据范围过滤
     *
     */
    public static void dataScopeFilter(JoinPoint joinPoint, LyUser lyUser) {
        StringBuilder sqlString = new StringBuilder();
        for(LyRole role :lyUser.getLyRoles()){
            if(role.getDataScope().equals(DATA_SCOPE_ROLE)){
                sqlString.append(StrUtil.format("AND ly_role.role_id =\"{}\"",role.getRoleId()));
            }
        }
        if(StrUtil.isNotEmpty(sqlString.toString())){
            Object params = joinPoint.getArgs()[0];
            if(ObjectUtil.isNotNull(params) && params instanceof BaseEntity){
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, sqlString);
            }
        }
    }

    /**
     * 拼接权限sql前先清空params.dataScope参数防止注入
     */
    private void clearDataScope(final JoinPoint joinPoint) {
        Object params = joinPoint.getArgs()[0];
        if (ObjectUtil.isNotNull(params) && params instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) params;
            baseEntity.getParams().put(DATA_SCOPE, "");
        }
    }







    /**
     * 业务逻辑结束时执行
     */
    @After("@annotation(dataJurisdiction)")
    public void afterMethod(DataJurisdiction dataJurisdiction) {
        System.out.println("业务逻辑结束时执行，无论异常与否都执行.......");
    }




}
